package com.hn658.user.sync.httpClient;

import java.io.IOException;

import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;

import com.hn658.framework.logging.Logger;
import com.hn658.framework.logging.LoggerFactory;
import com.hn658.framework.logging.enums.LogCategory;
import com.hn658.framework.shared.utils.JsonMapper;
import com.hn658.user.sync.exception.OApiException;

public class HttpHelper {

	private static Logger LOG = LoggerFactory.getLogger(HttpHelper.class);

	/** 闲置连接超时时间, 由bean factory设置，缺省为60秒钟 */
	private int defaultIdleConnTimeout = 60000;

	private int defaultMaxConnPerHost = 30;

	private int defaultMaxTotalConn = 80;

	/**
	 * HTTP连接管理器，该连接管理器必须是线程安全的.
	 */
	private HttpConnectionManager connectionManager;

	private static HttpHelper httpProtocolHandler = new HttpHelper();
	private static JsonMapper mapper = JsonMapper.nonEmptyMapper();

	/**
	 * 工厂方法
	 * 
	 * @return
	 */
	public static HttpHelper getInstance() {
		return httpProtocolHandler;
	}

	/**
	 * 私有的构造方法
	 */
	private HttpHelper() {
		// 创建一个线程安全的HTTP连接池
		connectionManager = new MultiThreadedHttpConnectionManager();
		connectionManager.getParams().setDefaultMaxConnectionsPerHost(
				defaultMaxConnPerHost);
		connectionManager.getParams().setMaxTotalConnections(
				defaultMaxTotalConn);

		IdleConnectionTimeoutThread ict = new IdleConnectionTimeoutThread();
		ict.addConnectionManager(connectionManager);
		ict.setConnectionTimeout(defaultIdleConnTimeout);

		ict.start();
	}

	public static HttpResponse httpGet(HttpRequest request) {
		HttpGet httpGet = new HttpGet(request.getUrl());
		CloseableHttpResponse response = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(2000).setConnectTimeout(2000).build();
		httpGet.setConfig(requestConfig);

		try {
			response = httpClient.execute(httpGet, new BasicHttpContext());

			if (response.getStatusLine().getStatusCode() != 200) {
				LOG.info(LogCategory.SYSTEM, "request url failed, http code="
						+ response.getStatusLine().getStatusCode() + ", url="
						+ request.getUrl());
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String resultStr = EntityUtils.toString(entity, "UTF-8");
				httpResponse = new HttpResponse();
				httpResponse.setStringResult(resultStr);
			}else{
				throw new OApiException(OApiException.GetDataError);
			}
		} catch (IOException e) {
			LOG.error(LogCategory.SYSTEM, "request url=" + request
					+ ", exception, msg=" + e.getMessage(), e);
			throw new OApiException(OApiException.ConnectError);
		} finally{
			try {
				response.close();
			} catch (IOException e) {
				LOG.error(LogCategory.SYSTEM, "连接关闭异常", e);
			}
		}

		return httpResponse;
	}

	public static HttpResponse httpPost(HttpRequest request, Object object)
			throws OApiException {
		HttpPost httpPost = new HttpPost(request.getUrl());
		CloseableHttpResponse response = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(2000).setConnectTimeout(2000).build();
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("Content-Type", "application/json");

		try {
			StringEntity requestEntity = new StringEntity(
					mapper.toJson(object), request.getCharset());
			httpPost.setEntity(requestEntity);

			response = httpClient.execute(httpPost, new BasicHttpContext());

			if (response.getStatusLine().getStatusCode() != 200) {

				LOG.info(LogCategory.SYSTEM, "request url failed, http code="
						+ response.getStatusLine().getStatusCode() + ", url="
						+ request.getUrl());
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String resultStr = EntityUtils.toString(entity,
						request.getCharset());
				httpResponse = new HttpResponse();
				httpResponse.setStringResult(resultStr);
			}else{
				throw new OApiException(OApiException.GetDataError);
			}
		} catch (IOException e) {
			LOG.error(LogCategory.SYSTEM, "request url=" + request
					+ ", exception, msg=" + e.getMessage(), e);
			throw new OApiException(OApiException.ConnectError);
		} finally{
			try {
				response.close();
			} catch (IOException e) {
				LOG.error(LogCategory.SYSTEM, "连接关闭异常", e);
			}
		}
		return httpResponse;

	}
}